﻿using System;
using System.Buffers;
using System.IO;
using System.Net.Security;
using ePipe;
using eTask.Extensions;
using Letter.IO.Binary;
using Letter.Net.SSL;

namespace Letter.Net.Tcp;

public abstract class ADefaultFixedSymbolBytesConnection : ATcpConnection
{
    public ADefaultFixedSymbolBytesConnection(byte[] symbol) : this(symbol, null, null)
    {
    }

    public ADefaultFixedSymbolBytesConnection(byte[] symbol, SSLOptions sslOptions, Func<Stream, SslStream> sslStreamFactory) 
        : base(sslOptions, sslStreamFactory)
    {
        if (symbol == null || symbol.Length == 0)
        {
            throw new ArgumentNullException(nameof(symbol));
        }

        if (symbol.Length > 8)
        {
            throw new Exception("Only symbols of length 8 are supported");
        }

        this.symbol = symbol;
    }

    private byte[] symbol;
    
    protected override void OnRcvBuffer(IPipeReader<byte> input, ref ReadOnlySequence<byte> buf)
    {
        var reader = buf.ToBytesReader();
        while (reader.TryFindPosition(this.symbol, out SequencePosition endPosition))
        {
            var buffer = reader.ReadBuffer(endPosition);
            var length = buffer.Length - this.symbol.Length;
            this.OnMessage(buffer.Slice(buffer.Start, length));
        }
        
        input.AdvanceTo(reader.End);
        input.Flush();
    }
    
    protected abstract void OnMessage(ReadOnlySequence<byte> buf);

    public void WriteAndPushAsync(ref ReadOnlySequence<byte> buf)
    {
        if (!this.Active)
        {
            return;
        }

        if (buf.Length == 0)
        {
            throw new ArgumentNullException(nameof(buf));
        }

        var output = this.Transport.Writer;
        var writer = output.ToBytesWriter();
        writer.WriteSequence(ref buf);
        writer.WriteBytes(this.symbol);
        output.FlushAsync().Ignore();
    }
}